﻿using MathNet.Numerics;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.LinearAlgebra;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Graph.Algorithm.Core.Quant
{
    public class QuantGenetic
    {

        #region builder 
        private static Random randomBuilder { get; set; } = new Random();
        private static VectorBuilder<double> vectorBuilder { get; set; } = Vector<double>.Build;
        private static MatrixBuilder<double> matBuilder { get; set; } = Matrix<double>.Build;

        #endregion


        public static int population_size { get; set; }
        /// <summary>
        /// 染色体数，对应需要寻优的参数个数        
        /// </summary>
        public static int chromosome_num { get; set; }
        public static int chromosome_length { get; set; }
        public static float max_value { get; set; }
        public static float min_value { get; set; }
        public static int iter_num { get; set; }
        public static float deta { get; set; }


        void Init(
            int _population_size,
            int _chromosome_num,
            int _chromosome_length,
            float _max_value,
            float _min_value,
            int _iter_num,
            float _deta)
        {
            // 初始化类参数
            //population_size(int):种群数
            //chromosome_num(int):染色体数，对应需要寻优的参数个数
            //chromosome_length(int):染色体长度
            //max_value(float):染色体十进制数值最大值
            //min_value(float):染色体十进制数值最小值
            //iter_num(int):迭代次数
            //deta(float):量子旋转角度 

            population_size = _population_size;
            chromosome_num = _chromosome_num;
            chromosome_length = _chromosome_length;
            max_value = _max_value;
            min_value = _min_value;
            iter_num = _iter_num;
            deta = _deta;

        }



        List<List<List<double>>> species_origin_angle()
        {
            //种群初始化
            //input: self(object):QGA类
            //output:population_Angle(list):种群的量子角度列表
            //population_Angle2(list):空的种群的量子角度列表，用于存储交叉后的量子角度列表


            //List<double> population_Angle = new List<double>();
            //List<double> population_Angle2 = new List<double>();

            List<List<List<double>>> population_Angle = new List<List<List<double>>>();

            for (int i = 0; i < chromosome_num; i++)
            {
                List<List<double>> angles = new List<List<double>>();
                for (int j = 0; j < population_size; j++)
                {
                    List<double> thetas = new List<double>();
                    for (int k = 0; k < chromosome_length; k++)
                    {
                        var angle = Math.PI * 2 * randomBuilder.NextDouble();// random.random()
                        thetas.Add(angle);
                    }
                    angles.Add(thetas);
                }
                population_Angle.Add(angles);
            }

            return population_Angle;
        }


        void population_Q(List<List<List<double>>> population_Angle)
        {
            var population_Q = new List<List<List<List<double>>>>();

            for (int i = 0; i < population_Angle.Count(); i++)
            {
                var tmp1 = new List<List<List<double>>>();// ##存储每个染色体所有取值的量子系数对    
                for (int j = 0; j < population_Angle[i].Count(); j++)
                {
                    var tmp2 = new List<List<double>>();//## 存储每个染色体的每个取值的量子对
                    var tmp3 = new List<double>();// ## 存储量子对的一半
                    var tmp4 = new List<double>();// ## 存储量子对的另一半
                    for (int k = 0; k < population_Angle[i][j].Count(); k++)
                    {
                        var a = population_Angle[i][j][k];
                        tmp3.Add(Math.Sin(a));
                        tmp4.Add(Math.Cos(a));
                    }
                    tmp2.Add(tmp3);
                    tmp2.Add(tmp4);
                    tmp1.Add(tmp2);
                }
                population_Q.Add(tmp1);
            }

        }

    }



}
